<?php
// +----------------------------------------------------------------------
// | OneThink [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013 http://www.onethink.cn All rights reserved.
// +----------------------------------------------------------------------
// | Author: 麦当苗儿 <zuojiazi@vip.qq.com> <http://www.zjzit.cn>
// +----------------------------------------------------------------------

namespace Wechat\Api;

use Wechat\Api\Api;
use Wechat\Model\TchatClientModel;

class ClientApi extends Api {
    /**
     * 构造方法，实例化操作模型
     */
    protected function _init() {
        $this->model = new TchatClientModel();
    }

    /**
     * 获取客户条目详情
     *
     * @param $id  int Id 或者 openId 字符串
     *
     * @return array 该条目的数组
     */
    public function getInfo($id,$field = true) {
        return $this->model->detail($id,$field);
    }

    /**
     * 更新客户信息
     *
     * @param $data
     * @return mixed
     */
    public function update($data){
        return $this->model->update($data);
    }

    /**
     * 获取客户Id
     *
     * @param $id  int Qrcode Id 或者 ticket 字符串
     *
     * @return array 该条目的数组
     */
    public function getClientId($openId) {
        return $this->model->getClientId($openId);
    }

    /**
     * 通过openid获取UID
     *
     * @param $uid
     * @return mixed
     */
    public function getOpenidByUid($uid) {
        return $this->model->getOpenidByUid($uid);
    }

    /**
     * 获取粉丝身上的标签
     *
     * @param $openid
     * @return mixed|string
     */
    public function getOpenidTags($openid){
        return get_openid_tags($openid);
    }

    /**
     * 创建标签
     *
     * @param $openid
     * @return mixed|string
     */
    public function createTag($name){
        $data = array(
            'tag'=>array(
                'name'=>$name
            )
        );
        return set_wechat_tag($data);
    }

    /**
     * 导入微信粉丝
     *
     * @param bool $nextOpenid
     * @return bool|mixed|string
     */
    public function importClient($nextOpenid=false){
        //从缓存中读取开始拉取的openid，没有缓存说明从未执行过，从头开始拉取
        //绝对判断是否等于false是为了区别传入的参数为空时执行强制从头拉取
        if(false === $nextOpenid){
            $nextOpenid = S('importNextOpenid')?S('importNextOpenid'):'';
        }
        //从服务器拉取数据
        $data = get_wechat_client($nextOpenid);
        //判断是否有错误
        if($data['errcode']){
           return false;
        }
        //返回拉取到的openid数组，最多不会超过10000个
        return $data;
    }

    /**
     * 设置客户的备注信息
     *
     * @param   string|int  $id         客户ID或对应粉丝openid
     * @param   string      $remark     备注的名称
     * @return bool
     */
    public function remark($openid,$remark){

        //判断是ID还是OPENID
        if(is_numeric($openid)){
            $id = $openid;
            $openid = $this->model->getOpenidById($openid);
        }

        //先设置到服务器获得返回结果
        $re = set_client_remark($openid,$remark);

        //返回结果成功时写入数据库
        if($re['errcode'] == 0){
            if($id === NULLL) $id = $this->model->getClientId($openid);
            $data = array(
                'id'=>$id,
                'remark'=>$remark
            );

            //写入数据库成功返回true
            $status = $this->model->save($data);
            if($status > 0){
                return true;
            }
        }
        //不成功返回False
        return false;
    }

    /**
     * 设置客户的标签信息
     * 微信端只开放了批量设置客户标签的功能，所以单个客户的标签设置也是用的批量函数
     * TODO 根据客户身上标签数量限制只能设置三个标签
     *
     * @param array $openid     客户ID或对应粉丝openid
     * @param array $tagid_list 要设置的tagid
     * @return bool
     */
    public function tagid_list($openid,$tagid_list){
        if(is_array($openid)){
            $error = $this->bathchClientTag($openid,$tagid_list);
        }else{
            $error = $this->setClientTag($openid,$tagid_list);
        }

        //有错误发生时返回错误信息。
        return empty($error)?true:$error;
    }

    /**
     * 单个打标签
     */
    private function setClientTag($openid,$tagid_list){

        $error = '';
        if(is_numeric($openid)){
            $map['id'] = $openid;
            $openid = $this->model->getOpenidById($openid);
        }else{
            $map['openid'] = $openid;
        }

        //遍历tagid，转换文字标签为数字ID
        foreach($tagid_list as $k => $tagid){
            if(!is_numeric($tagid)){//如果不是数字形式的标签ID值
                $tagid_list[$k] = get_tag_id($tagid);
            }
        }

        //整理标签数据
        $old = $this->model->where($map)->getField('tagid_list');//原有标签
        $old = str2arr($old);

        $new = $tagid_list?$tagid_list:array();//新设置标签
        $deleteTags = array_diff($old,$new);//用旧的标签比较新的标签，获取差集(即要删除的ID)
        $addTags = array_diff($new,$old);//用新的标签比较旧的标签，获取差集(即要增加的ID)

        $num = count($old)-count($deleteTags)+count($addTags);
        if($num > 3){
            return '客户标签数量已超过三个，请删除不需要的标签后再设置';
        }

        //有要删除的数据就执行删除操作
        if($deleteTags){
            foreach($deleteTags as $v){
                $del = batch_client_tag($openid,$v,'untagging');
                if($del['errcode'] != 0){
                    $error .= date('Y-m-d H:m:s').' 删除标签id'.$v.'时发生错误，错误信息为：'. $del['errmsg'].'\r\n';
                }
            }
        }

        //有要增加的数据就执行新增操作
        if($addTags){
            foreach($addTags as $v){
                $del = batch_client_tag($openid,$v,'tagging');
                if($del['errcode'] != 0){
                    $error .= date('Y-m-d H:m:s').' 新增标签id'.$v.'时发生错误，错误信息为：'. $del['errmsg'].'\r\n';
                }
            }
        }

        $id = $this->model->getIdByOpenid($openid);
        //组织存储数据
        $data['id']=$id;
        $data['tagid_list'] = get_openid_tags($openid);//新标签从服务器下载
        //存储到本地数据
        $re = $this->model->save($data);
        //错误时返回错误信息
        if($re === false || $re === 0){
            $error .= date('Y-m-d H:m:s').' 更新本地客户ID为：'.$id.'的标签数据失败。\r\n';
        }

        return empty($error)?true:$error;

    }
    /**
     * 批量打标签到客户身上
     */
    private function bathchClientTag($openid,$tagid_list){
        $error = '';
        //要用到的openid是数组形式的
        if(!is_array($openid)){
            $openid = str2arr($openid);
        }

        //转化数组中的数字ID为openid字符串
        foreach($openid as $k => $v){
            if(is_numeric($v)){
                $openid[$k] = $this->model->getOpenidById($v);
            }
        }

        //遍历tagid，逐个将标签批量增加到传入的openid数组对应的客户身上
        foreach($tagid_list as $k => $tagid){

            if(!is_numeric($tagid)){//如果不是数字形式的标签ID值
                $tagid_list[$k] = get_tag_id($tagid);
            }
            //打标签到客户身上
            $re = batch_client_tag($openid,$tagid,'tagging');
            if($re['errcode'] != 0){//打标签错误时返回错误代码
                $error .= date('Y-m-d H:m:s').' 新增标签id'.$v.'时发生错误，错误信息为：'. $re['errmsg'].'\r\n';
            }
        }

        //获取本次影响的客户的本地ID集合
        $ids = $this->model->getIdByOpenid($openid);

        //依次将新打上的标签同步到本地数据库
        foreach($ids as $id){
            $openid = $this->model->getOpenidById($id);

            //组织存储数据
            $data['id']=$id;
            $data['tagid_list'] = get_openid_tags($openid);//新标签从服务器下载
            //存储到本地数据
            $re = $this->model->save($data);
            //错误时返回错误信息
            if($re === false || $re === 0){
                $error .=  date('Y-m-d H:m:s').' 更新本地客户ID为：'.$id.'的标签数据失败。\r\n';
            }
        }

        return empty($error)?true:$error;

    }

    /**
     * 获取出错信息
     * @return mixed
     */
    public function getError() {
        return $this->model->getError();
    }

    /**
     * 粉丝取消关注时执行
     *
     * @param $openId str 客户openId
     */
    public function unSubscribe($openId) {
        $this->model->unSubscribe($openId);
    }

    /**
     * 测试调用
     */
    public function test() {
        return 'This is message in ClientApi class and test method';
    }

}
